Ext.define('Ext.ux.store.FormulaicStore', {
    extend: 'Ext.data.Store',
    alias:'widget.formulaicstore',
    constructor:function(config) {
        //Calling the parent class constructor
        this.callParent(arguments);
        //Initializing the component
        this.initConfig(config);
        if (config.autoCalculate)
            this.initiateCalculations.call(this);
    },

    /*
     * This function initiates calculations from left to right, and top to bottom, excel sheet style.
     * The dependent rows are always assumed to be on the right and bottom. Thus, when any value that needs to be
     * computed already has its component operands' values calculated.
     * */
    initiateCalculations:function() {
        for (var i = 0; i < this.getCount(); i++) {
            for (var j = 0; j < this.formulaColumns.length; j++) {
                var currentFormulaColumn = this.formulaColumns[j] + 'Formula';
                var currentDestinationColumn = this.formulaColumns[j];
                var currentRecord = this.getAt(i);
                var currentFormula = currentRecord.get(currentFormulaColumn);
                // Start calculating formulae only if there is a formula associated with a column.
                // Else, do not change the value of the column at all.
                this.constructTokensAndCalculateValue(currentFormula, currentRecord, currentDestinationColumn);
            }
        }
    },
    constructTokensAndCalculateValue:function(formula, record, destinationColumn) {

        if (formula && formula != '') {
            var tokens = getTokens(formula);

            var evalStr = '';
            //Loop through the tokens and substitute values as you move through
            while (tokens.moveNext()) {

                var token = tokens.current();

                if (token.type == TOK_TYPE_OPERAND) {

                    if (token.value.indexOf(':') != -1) {
                        //This is an actual OPERAND like A1, B1, etc.
                        var operandSplit = token.value.split(':');
                        var dataIndex = operandSplit[0];
                        var recordIndex = operandSplit[1];


                        //Replace the operands (A1, B1, etc ) with the actual value
                        try {
                            evalStr += this.getAt(recordIndex).get(dataIndex);
                        }
                        catch(ex) {
                            console.log(formula);
                        }

                    } else {
                        //Current token is NOT AN OPERAND. It is more likely a number.
                        //Add to the eval string and proceed.
                        evalStr += token.value;
                    }
                } else {
                    evalStr += token.value;
                }
            }
            //Find out the value for the formula.
            
            var valueToBeSet = Math.ceil(eval(evalStr));
            record.set(destinationColumn, valueToBeSet);
            record.commit();
        }
    },
    /*
     * Determines the row and column which just got updated, and initiates calculations starting from the cell onwards.
     * */
    initiateCalculationsFromEditedCellOnwards:function(editedColumnIndex, editedRowIndex) {
        for (var i = editedRowIndex; i < this.getCount(); i++) {
            /*
             * If a row was edited thus:
             *
             * ***__************
             *
             * Start the j from the next column of the edited column thus:
             *      v
             * ***__***********
             *
             * Only for the same row as the edited field. Else, start the calculations from the 0th column in the next row
             * V
             * ****************
             * */

            for (var j = i > editedRowIndex ? 0 : editedColumnIndex; j < this.formulaColumns.length; j++) {
                var currentFormulaColumn = this.formulaColumns[j] + 'Formula';
                var currentDestinationColumn = this.formulaColumns[j];
                var currentRecord = this.getAt(i);
                var currentFormula = currentRecord.get(currentFormulaColumn);
                // Start calculating formulae only if there is a formula associated with a column.
                // Else, do not change the value of the column at all.
                this.constructTokensAndCalculateValue(currentFormula, currentRecord, currentDestinationColumn);
            }
        }
    }
});